package etf.db40;


import java.util.Random;


import com.db4o.ObjectSet;
import com.db4o.query.Query;

import etf.library.Address;
import etf.library.Author;
import etf.library.Book;
import etf.library.Category;
import etf.library.Employee;
import etf.library.Library;
import etf.library.Member;

public class ComplexDb4o extends Db4oUtil {
	final static String DB4OFILENAME = "ComplexTest";

	public ComplexDb4o() {
		createDatabase(DB4OFILENAME);
	}

	public ComplexDb4o(String fileName) {
		createDatabase("/" + fileName + ".db40");
	}
	
	public long insert(int size){
		long elapsedTime = 0;
		try {
			long startTime = System.currentTimeMillis();
			for (int i = 0; i < size/100; i++) {
				Address address = new Address("Splitska_"+i, i, "Sarajevo", i, "BiH");
				Library lib = new Library("Biblioteka_"+i, "033-120-240", "lib@lib.ba", address);
				Author author = new Author("Peter_"+i, "Lacko", "Male",i);
				Category cat = new Category("Category_"+i);
				
				for (int j = 0; j < 100; j++) {
					Member m = new Member("John_"+j, "Johns",i,"member@lib.ba");
					Book book = new Book("Book_"+j, j, cat, author);					
					Employee emp = new Employee("Jane_"+j, "Janis", j, j, address);
					lib.hireAnEmployee(emp);
					lib.registerAMember(m);
					lib.addABook(book);
					m.rentABook(book);
					m.setLibrary(lib);
					book.addRenter(m);
				}
				db.store(lib);
			}
			db.commit();
			long stopTime = System.currentTimeMillis();
			elapsedTime = stopTime - startTime;
		} catch (Exception e) {
			e.printStackTrace();
			db.close();
		}		
		return elapsedTime;
	}
	
	/*
	 *   QUERY ONE
	 */
	
	public long queryOne(int size){
		long elapsedTime = 0;
		double suma = 0;
		try {
			for (int i = 0; i < 4; i++) {
				long startTime = System.currentTimeMillis();
				int parameter = getRandom(size / 100);
				Query q = db.query();
				q.constrain(Book.class);
				q.descend("renters").descend("phoneNumber").constrain(parameter)
				.and(q.descend("year").constrain(getRandom(100)))
				.and(q.descend("category").descend("categoryName").constrain("Category_" + parameter));
				ObjectSet<Book> result = q.execute();
				if (result.hasNext()) {
					Book e = result.next();
					System.out.println(e.getTitle());
				}
				long stopTime = System.currentTimeMillis();
				elapsedTime = stopTime - startTime;
				suma +=elapsedTime;
			}
			suma = suma/4;
		} catch (Exception e) {
			e.printStackTrace();
			db.close();
		}		
		return (long)suma;
	}
	
	/*
	 *   QUERY TWO
	 */
	public long queryTwo(int size){
		long elapsedTime = 0;
		double suma = 0;
		try {
			for (int i = 0; i < 4; i++) {
				long startTime = System.currentTimeMillis();
				Query q = db.query();
				q.constrain(Member.class);
				q.descend("rentedBooks").descend("year").constrain(getRandom(100))
				.and(q.descend("rentedBooks").descend("category")
						.descend("categoryName").constrain("Category_" + getRandom(size / 100)));
				ObjectSet<Member> result = q.execute();
				if (result.hasNext()) {
					Member m = result.next();
					System.out.println(m.getFirstName());
				}
				long stopTime = System.currentTimeMillis();
				elapsedTime = stopTime - startTime;
				suma +=elapsedTime;
			}
			suma = suma/4;
		} catch (Exception e) {
			e.printStackTrace();
			db.close();
		}		
		return (long)suma;
	}
	
	/*
	 *   QUERY THREE
	 */
	public long queryThree(final int size){
		long elapsedTime = 0;
		double suma = 0;
		try {
			for (int i = 0; i < 4; i++) {
				long startTime = System.currentTimeMillis();
				int parameter = getRandom(size / 100);
				Query q = db.query();
				q.constrain(Library.class);
				q.descend("employees").descend("salary").constrain(
						getRandom(100)).and(
						q.descend("members").descend("phoneNumber").constrain(
								parameter)).and(
						q.descend("books").descend("category").descend(
								"categoryName").constrain(
								"Category_" + parameter)).and(
						q.descend("address").descend("houseNumber").constrain(
								parameter)).and(
						q.descend("books").descend("year").constrain(
								getRandom(100))).and(
						q.descend("members").descend("firstName").constrain(
								"John_" + getRandom(100)));
				ObjectSet<Library> result = q.execute();
				if (result.hasNext()) {
					Library l = result.next();
					System.out.println(l.getLibraryName());
				}
				long stopTime = System.currentTimeMillis();
				elapsedTime = stopTime - startTime;
				suma +=elapsedTime;
			}
			suma = suma/4;
		} catch (Exception e) {
			e.printStackTrace();
			db.close();
		}		
		return (long)suma;
	}
	
	/*
	 *   QUERY FOUR
	 */
	public long queryFour(final int size){
		long elapsedTime = 0;
		double suma = 0;
		try {
			for (int i = 0; i < 4; i++) {
				long startTime = System.currentTimeMillis();
				int parameter = getRandom(size / 100);
				Query q = db.query();
				q.constrain(Member.class);
				q.descend("library").descend("address").descend("houseNumber").constrain(parameter)
				.and(q.descend("phoneNumber").constrain(parameter))
				.and(q.descend("rentedBooks").descend("category").descend("categoryName").constrain("Category_" + parameter))
				.and(q.descend("rentedBooks").descend("author").descend("age").constrain(parameter))
				.and(q.descend("rentedBooks").descend("year").constrain(getRandom(100)));
				ObjectSet<Member> result = q.execute();
				if (result.hasNext()) {
					Member m = result.next();
					System.out.println(m.getFirstName());
				}
				long stopTime = System.currentTimeMillis();
				elapsedTime = stopTime - startTime;
				suma +=elapsedTime;
			}
			suma = suma/4;
		} catch (Exception e) {
			e.printStackTrace();
			db.close();
		}		
		return (long)suma;
	}
	
	/*
	 *   UPDATE
	 */
	public long update (int size){
		long elapsedTime = 0;
		
		try {
			long startTime = System.currentTimeMillis();

			int parameter = getRandom(size/100);
			Query q = db.query();
			q.constrain(Member.class);
			q.descend("library").descend("address").descend("houseNumber").constrain(parameter)
			.and(q.descend("phoneNumber").constrain(parameter))
			.and(q.descend("rentedBooks").descend("category").descend("categoryName").constrain("Category_"+parameter))
			.and(q.descend("rentedBooks").descend("author").descend("age").constrain(parameter))
			.and(q.descend("rentedBooks").descend("year").constrain(getRandom(100)));
		
			ObjectSet<Member> result = q.execute();
			if(result.hasNext()){
				Member m = result.next();
				m.setFirstName("New_Name");
				db.store(m);
				db.commit();
				System.out.println(m.getFirstName());
			}
			
			long stopTime = System.currentTimeMillis();
			elapsedTime = stopTime - startTime;
		} catch (Exception e) {
			e.printStackTrace();
			db.close();
		}		
		return elapsedTime;
	}
	
	
	private int getRandom(int max){
		Random r = new Random();
        return r.nextInt(max); 
	}

}
